/*
RetroLeague - Mobile application for The Retro League Podcast
Copyright (C) 2010-2012 Hugues Johnson

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software 
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package com.huguesjohnson.retroleague;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;

import com.huguesjohnson.retroleague.fb.AlbumItem;
import com.huguesjohnson.retroleague.fb.FacebookJSONParser;
import com.huguesjohnson.retroleague.fb.PhotoItem;
import com.huguesjohnson.retroleague.util.HttpFetch;
import com.huguesjohnson.retroleague.util.RestInvoke;

public class FacebookActivity extends Activity{
	private final static String TAG="FacebookActivity";
	private String currentStatus;
	private String albumsJson;
	private String errorText;
	private ArrayAdapter<AlbumItem> albumArrayAdapter;
	private AlbumItem selectedAlbum;
	private PhotoItem selectedImage;
	//ui stuff
	private AlertDialog aboutDialog;
	private TextView textViewStatus;
	private TextView textViewAlbumDescription;
	private Gallery gallerySelectedAlbum;
	private Spinner spinnerSelectAlbum;
	private ImageView imageViewSelectedImage;
	private ProgressBar progressBarStatus;
	//menu constants
	private final static int MENU_BACK=0;
	private final static int MENU_ABOUT=1;
	private final static int MENU_REFRESH=2;

	private class UpdateAlbumGalleryTask extends AsyncTask<String,String,ArrayList<PhotoItem>>{
		@Override
		protected ArrayList<PhotoItem> doInBackground(String... params){
			try{
				Resources r=getResources();
        		//invoke the API to get posts
        		long startTime=System.currentTimeMillis();
        		String facebookUrlPhotos=(r.getString(R.string.facebook_url_photos)).replace("[ALBUMID]",selectedAlbum.getId());
        		String photosJson=RestInvoke.invoke(facebookUrlPhotos);
        		long endTime=System.currentTimeMillis();
                Log.d(TAG,"Time to download photos="+(endTime-startTime)+"ms");
        		//parse out the latest status
                startTime=endTime;
                ArrayList<PhotoItem> photos=FacebookJSONParser.parsePhotos(photosJson);
        		endTime=System.currentTimeMillis();
                Log.d(TAG,"Time to parse latest status="+(endTime-startTime)+"ms");
				return(photos);
			}catch(Exception x){
				Log.e(TAG,"UpdateAlbumGalleryTask",x);
    	    	return(null);
			}
	     }

	     public void onPostExecute(ArrayList<PhotoItem> photos){
	    	 if((photos==null)||(photos.size()<1)){
	    		 textViewAlbumDescription.setText("Unable to download "+selectedAlbum.getName());
	    	 }else{
	    		 textViewAlbumDescription.setText(selectedAlbum.getDescription());
	    		 gallerySelectedAlbum.setAdapter(new AlbumImageAdapter(getApplicationContext(),photos));
	    	 }
	     }
	 }
	
	private class DownloadImageTask extends AsyncTask<String,String,Bitmap>{
		@Override
		protected Bitmap doInBackground(String... params){
			try{
				Log.d(TAG,"DownloadImageTask.doInBackground");
				String imageUrl=selectedImage.getSourceUrl();
				Log.d(TAG,"DownloadImageTask.doInBackground, imageUrl="+imageUrl);
				Bitmap bitmap=ImageCache.get(imageUrl);
				if(bitmap!=null){return(bitmap);}
        		long startTime=System.currentTimeMillis();
				bitmap=HttpFetch.fetchBitmap(imageUrl);
        		long endTime=System.currentTimeMillis();
        		Log.d(TAG,"DownloadEpisodeLogoTask.doInBackground, Time to fetch bitmap="+(endTime-startTime)+"ms");
				ImageCache.put(imageUrl,bitmap);
				return(bitmap);
			}catch(IOException iox){
				Log.e(TAG,"DownloadImageTask",iox);
    	    	return(null);
			}
	     }

	     public void onPostExecute(Bitmap result){
	    	 imageViewSelectedImage.setImageBitmap(result);
	     }
	 }
	
	private class LoadStatusTask extends AsyncTask<String,String,String>{
		@Override
		protected String doInBackground(String... params){
			Resources r=getResources();
        	long startTime=0;
        	long endTime=0;
        	//read rss feed to get posts
        	try{
        		//hit the rss feed
        		startTime=System.currentTimeMillis();
        		InputStream in=HttpFetch.fetch(r.getString(R.string.facebook_url_rss_posts));
        		endTime=System.currentTimeMillis();
                Log.d(TAG,"Time to get input stream for rss="+(endTime-startTime)+"ms");
        		//read the latest status
    	        startTime=endTime;
                boolean itemOpen=false;
                boolean setStatus=false;
                BufferedReader reader=new BufferedReader(new InputStreamReader(in));
    	        String currentLine=null;
    	        while((!setStatus)&&((currentLine=reader.readLine())!=null)){
    	           	if(currentLine.indexOf("<item>")>=0){
    	           		itemOpen=true;
    	           	}else if(itemOpen){
    	           		int indexOf=currentLine.indexOf("<description>");
    	           		if(indexOf>=0){
    	           			int endIndex=currentLine.indexOf("</description>");
    	           			String description=currentLine.substring(indexOf+13,endIndex);
        	           		currentStatus=Html.fromHtml(description).toString();
        	           		setStatus=true;
    	           		}else if(currentLine.indexOf("</item>")>=0){
    	           			itemOpen=false;
    	           		}	
    	           	}
    	        }
    	        in.close();
        		endTime=System.currentTimeMillis();
                Log.d(TAG,"Time to parse latest status="+(endTime-startTime)+"ms");
                //set a default message if nothing was found
                if((currentStatus!=null)&&(currentStatus.length()<1)){
                	currentStatus="Unable to retrieve latest posts. You might have an internet connectivity or Facebook changed their API again. If it's the latter check the Android Market for an update soon.";
                }
        	}catch(Exception x){
        		Log.e(TAG,"LoadStatusThread->RSS feed",x);
        		errorText=x.getMessage();
        	}
        	//invoke the API to get albums
        	try{
        		startTime=System.currentTimeMillis();
        		albumsJson=RestInvoke.invoke(r.getString(R.string.facebook_url_albums));
        		endTime=System.currentTimeMillis();
                Log.d(TAG,"Time to download albums="+(endTime-startTime)+"ms");
        		//parse the albums
                startTime=endTime;
                ArrayList<AlbumItem> albums=FacebookJSONParser.parseAlbums(albumsJson);
        		endTime=System.currentTimeMillis();
                Log.d(TAG,"Time to parse albums="+(endTime-startTime)+"ms");
        		//update the select album spinner
                if(albums.size()>0){
                	albumArrayAdapter=new ArrayAdapter<AlbumItem>(getApplicationContext(),android.R.layout.simple_spinner_item,albums);
                }
            }catch(Exception x){
    			Log.e(TAG,"LoadStatusThread->albums",x);
            	errorText=x.getMessage();
            }
            return(null);
		}
		
	     public void onPostExecute(String result){
	    	 updateUI();
	     }
	}
	
	public class AlbumSelectedListener implements OnItemSelectedListener{
		public void onItemSelected(AdapterView<?> parent,View view,int pos,long id){
			if(spinnerSelectAlbum.getCount()>1){
				selectedAlbum=(AlbumItem)spinnerSelectAlbum.getItemAtPosition(pos);
				updateAlbum();
			}
		}

	    public void onNothingSelected(AdapterView<?> parent){/* not implemented */}
	}	
	
	public class OnPhotoClickedListener implements OnItemClickListener{
		@Override
		public void onItemClick(AdapterView<?> parent,View view,int position,long id){
			selectedImage=(PhotoItem)gallerySelectedAlbum.getItemAtPosition(position);
			showImageDialog();
		}
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu){
		try{
			menu.add(0,MENU_ABOUT,0,"About").setIcon(R.drawable.menu_about);
			menu.add(0,MENU_REFRESH,1,"Refresh").setIcon(R.drawable.menu_refresh);
			menu.add(0,MENU_BACK,2,"Back to main menu").setIcon(R.drawable.menu_back);
			return(true);
		}catch(Exception x){
			Log.e(TAG,"onCreateOptionsMenu",x);
			return(false);
		}
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item){
		try{
			switch(item.getItemId()){
			case MENU_REFRESH:{this.refreshStatus();return(true);}
			case MENU_ABOUT:{this.showAboutDialog(); return(true);}
			case MENU_BACK:{this.finish();return(true);}
			default:{return(false);}
			}
		}catch(Exception x){
			if(item!=null){
				Log.e(TAG,"onOptionsItemSelected: item.getItemId()="+item.getItemId(),x);
			}else{
				Log.e(TAG,"onOptionsItemSelected: item is null",x);
			}
			return(false);
		}
	}	
	
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.facebooklayout);
        this.textViewStatus=(TextView)findViewById(R.id.TextViewLatestStatus);
        this.textViewAlbumDescription=(TextView)findViewById(R.id.TextViewAlbumDescription);
        this.spinnerSelectAlbum=(Spinner)findViewById(R.id.SpinnerSelectAlbum);
        this.spinnerSelectAlbum.setOnItemSelectedListener(new AlbumSelectedListener());
        this.gallerySelectedAlbum=(Gallery)findViewById(R.id.GallerySelectedAlbum);
        this.gallerySelectedAlbum.setOnItemClickListener(new OnPhotoClickedListener());
        this.progressBarStatus=(ProgressBar)findViewById(R.id.ProgressBarFacebookStatus);
		//link movement
        TextView textViewLink=(TextView)findViewById(R.id.TextViewFacebookLink);
        textViewLink.setMovementMethod(LinkMovementMethod.getInstance());
		//set the link to the facebook page
		textViewLink.setText(Html.fromHtml(this.getResources().getString(R.string.facebook_link_mobile)));
    }

	@Override
	protected void onResume(){
		super.onResume();
		//in case we came here after the user navigated away by clicking on the site link in the about dialog
		if((aboutDialog!=null)&&(aboutDialog.isShowing())){
			return;
		}
		//load the status
		if((this.currentStatus==null)||(this.currentStatus.length()<1)){
			this.refreshStatus();
		}
	}
	
	private void refreshStatus(){
		//get the latest status
		try{			
			this.progressBarStatus.setVisibility(View.VISIBLE);
			this.textViewStatus.setText(this.getResources().getString(R.string.status_fb_updating));
			new LoadStatusTask().execute("");
		}catch(Exception x){
			Log.e(TAG,"onResume",x);
			this.showErrorDialog(x);
		}
	}
	
	private void updateUI(){
		//latest status
		if((this.currentStatus==null)||(this.currentStatus.length()<1)){
			StringBuffer errorTextBuffer=new StringBuffer("Unable to retreive latest status.");
			if((this.errorText!=null)&&(this.errorText.length()>0)){
				errorTextBuffer.append(" Reason: ");
				errorTextBuffer.append(this.errorText);
			}
			this.textViewStatus.setText(errorTextBuffer.toString());
		}else{
			this.textViewStatus.setText(Html.fromHtml(this.currentStatus));
		}
		//update the select album spinner
		if((this.albumArrayAdapter==null)||(this.albumArrayAdapter.isEmpty())){
	      	ArrayList<String> defaultList=new ArrayList<String>();
	      	defaultList.add("No albums found");
	      	ArrayAdapter<String> defaultAdapter=new ArrayAdapter<String>(getApplicationContext(),android.R.layout.simple_spinner_item,defaultList);
	      	spinnerSelectAlbum.setAdapter(defaultAdapter);
	      	spinnerSelectAlbum.setEnabled(false);
		}else{
	      	spinnerSelectAlbum.setAdapter(this.albumArrayAdapter);
	      	spinnerSelectAlbum.setEnabled(true);
		}
		progressBarStatus.setVisibility(View.GONE);
	}
    
	private void updateAlbum(){
		this.gallerySelectedAlbum.setEnabled(false);
		this.textViewAlbumDescription.setText("Loading "+this.selectedAlbum.getName()+"...");
		new UpdateAlbumGalleryTask().execute("");
	}
	
	private void showErrorDialog(Exception x){
		try{
	        new AlertDialog.Builder(this)
	   		.setTitle(R.string.app_name)
	   		.setMessage(x.getMessage())
	   		.setPositiveButton("Close", null)
	   		.show();	
		}catch(Exception reallyBadTimes){
			Log.e(TAG,"showErrorDialog",reallyBadTimes);
		}
	}
	
	private void showImageDialog(){
		try{
			//create the dialog
			LayoutInflater inflater=(LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
			View layout=inflater.inflate(R.layout.viewimagelayout,(ViewGroup)findViewById(R.id.ViewImageDialogRoot));
			AlertDialog.Builder builder=new AlertDialog.Builder(this);
			builder.setView(layout);
			builder.setTitle("View Image");
			builder.setPositiveButton("Close",null);
			AlertDialog imageDialog=builder.create();
			//show the dialog
			imageDialog.show();
			this.imageViewSelectedImage=(ImageView)imageDialog.findViewById(R.id.ImageViewSourceImage);
			//load the image
			new DownloadImageTask().execute("");
		}catch(Exception x){
			Log.e(TAG,"showImageDialog",x);
		}	
	}
	
	private void showAboutDialog(){
		try{
			//create the dialog
			if(this.aboutDialog==null){
				LayoutInflater inflater=(LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
				View layout=inflater.inflate(R.layout.aboutdialoglayout,(ViewGroup)findViewById(R.id.AboutDialogRoot));
				AlertDialog.Builder builder=new AlertDialog.Builder(this);
				builder.setView(layout);
				builder.setTitle("About");
				builder.setPositiveButton("Close",null);
				this.aboutDialog=builder.create();
			}
			//show the dialog
			this.aboutDialog.show();
		}catch(Exception x){
			Log.e(TAG,"showAboutDialog",x);
		}	
	}
}